from fastapi import HTTPException
from model.model import User, Role, Authorization
from package.fastapi.cache import authorization_cache


class AuthorizationView(Authorization):

    @classmethod
    def post_authorization(cls, session, user_id, expired_at, description):
        item = cls.create_item(session, body=dict(user_id=user_id, expired_at=expired_at, description=description))
        authorization_cache.set(item.id, user=item.user, expired_at=expired_at)
        return item

    @classmethod
    def patch_authorization(cls, session, id, update):
        item = cls.update_item(session, filter_=[cls.id == id], update=update)
        authorization_cache.set(item.id, user=item.user, expired_at=item.expired_at)
        return item

    @classmethod
    def delete_authorization(cls, session, ids):
        count = cls.delete_items(session, filter_=[cls.id.in_(ids)])
        for id in ids:
            authorization_cache.delete(id)
        return count

    @classmethod
    def load_database2cache(cls, session):
        items = cls.get_items(session)
        for item in items:
            authorization_cache.set(item.id, user=item.user, expired_at=item.expired_at)


class RoleUserView(Role):

    @classmethod
    def get_role_users(cls, session, id, q):
        item = session.query(cls).filter(cls.id == id).first()
        return User.keyword_query(item.users, q).all()

    @classmethod
    def bind_role_users(cls, session, id, user_ids):
        """绑定角色到用户"""
        item = session.query(cls).filter(cls.id == id).first()

        uids = set(user_ids) - set(_user.id for _user in item.users.all())  # 可能重复添加
        if not uids:
            return 0

        users = session.query(User).filter(User.id.in_(uids)).all()
        item.users.extend(users)
        session.commit()
        return len(users)

    @classmethod
    def delete_role_users(cls, session, id, user_ids):
        item = session.query(cls).filter(cls.id == id).first()
        users = session.query(User).filter(User.id.in_(user_ids)).all()

        count = 0
        for _user in users:
            item.users.remove(_user)
            count += 1

        session.commit()
        return count


class UserView(User):
    @classmethod
    def edit_password(cls, session, id, old, new):
        item = cls.get_item(session, filter_=[cls.id == id])
        if not item:
            return {}

        if item.password != old:
            raise HTTPException(status_code=400, detail='密码输入错误')
        setattr(item, 'password', new)
        session.commit()
        return {}
